/**
 * Axios HTTP请求封装
 * 功能：
 * 1. 请求/响应拦截器
 * 2. 请求取消
 * 3. 请求超时处理
 * 4. 统一错误处理
 * 5. 请求队列管理
 * 6. 修复：接口返回大整数精度丢失问题
 * 7. 支持：请求参数传递 bigint 数据
 * 8. 支持：AbortController 取消请求
 */

import axios from "axios";
import JSONBig from "json-bigint";
import { getToken, removeToken } from "./auth";
import env from "./env";
import { showToast } from "./tools";
import configApi from "@/config/env";

// 获取当前环境配置，添加容错处理
const getCurrentEnv = () => {
  const envName = process.env.NAME_ER || "test"; // 默认使用 development 环境  pet test

  if (!configApi[envName]) {
    return configApi.development || {};
  }

  return configApi[envName];
};

const currentConfig = getCurrentEnv();

// 请求队列（用于取消重复请求）
const pendingRequests = new Map();

axios.defaults.adapter = function (config) {
  const jsonBig = JSONBig({ storeAsString: false });

  // 处理请求数据，确保 bigint 数据正确序列化
  let requestData = config.data;
  if (requestData && typeof requestData === "object") {
    try {
      // 如果数据是对象且包含 bigint，使用 JSONBig 序列化
      requestData = jsonBig.stringify(requestData);
    } catch (err) {
      // 如果序列化失败，回退到默认处理
      requestData = JSON.stringify(requestData);
    }
  }

  return new Promise((resolve, reject) => {
    // 创建请求任务
    const requestTask = uni.request({
      method: config.method.toUpperCase(),
      url: (config.baseURL || "") + config.url,
      data: requestData, // 使用处理后的数据
      header: config.headers,
      timeout: config.timeout,
      dataType: "String",
      success: (res) => {
        resolve({
          data: jsonBig.parse(res.data),
          status: res.statusCode,
          statusText: res.errMsg || "ok",
          headers: res.header,
          config,
        });
      },
      fail: (err) => {
        reject(err);
      },
    });

    // 支持 AbortController 取消请求
    if (config.signal) {
      const onAbort = () => {
        // 取消请求
        requestTask.abort();
        // 创建一个取消错误
        const error = new Error("Request aborted");
        error.code = "ERR_CANCELED";
        error.isCancel = true;
        reject(error);
        // 清理事件监听
        config.signal.removeEventListener("abort", onAbort);
      };

      if (config.signal.aborted) {
        onAbort();
      } else {
        config.signal.addEventListener("abort", onAbort);
      }
    }
  });
};

// 生成请求唯一Key
const generateRequestKey = (config) => {
  const { url, method, params, data } = config;
  // 使用 JSONBig 处理数据，支持 bigint
  const jsonBig = JSONBig({ storeAsString: false });

  return [url, method, jsonBig.stringify(params), jsonBig.stringify(data)].join(
    "&"
  );
};

// 移除请求
const removePendingRequest = (key, cancel) => {
  if (pendingRequests.has(key)) {
    if (cancel) {
      const cancelFn = pendingRequests.get(key);
      cancelFn && cancelFn(); // 执行取消函数
    }
    pendingRequests.delete(key);
  }
};

// 创建 axios 实例
const http = axios.create({
  // baseURL: env.baseUrl,
  baseURL:
    currentConfig.requestBaseUrl ||
    env.baseUrl ||
    "http://47.236.172.98:8200/api/jingang",
  timeout: 30000, // 30s 超时
  headers: {
    "Content-Type": "application/json",
  },
  // 使用 json-bigint 序列化请求数据，支持 bigint
  transformRequest: [
    function (data, headers) {
      if (data && typeof data === "object") {
        try {
          const jsonBig = JSONBig({ storeAsString: false });
          return jsonBig.stringify(data);
        } catch (err) {
          // 如果 JSONBig 序列化失败，回退到默认处理
          return JSON.stringify(data);
        }
      }
      return data;
    },
  ],
  // 使用 json-bigint 解析响应
  transformResponse: [
    function (data) {
      try {
        return JSONBig({ storeAsString: true }).parse(data);
      } catch (err) {
        return data;
      }
    },
  ],
});

// 扩展 post 方法，支持第三个参数传递配置
http.post = function (url, data, config = {}) {
  return this.request({
    method: "post",
    url,
    data,
    ...config,
  });
};

// 请求拦截器
http.interceptors.request.use(
  (config) => {
    // 携带 token
    if (getToken()) {
      config.headers.Authorization = "Bearer " + getToken();
    }

    // 如果没有使用 AbortController，则使用内部的取消机制
    if (!config.signal) {
      // 生成请求 key
      const requestKey = generateRequestKey(config);
      // 如果有重复请求，取消之前的
      removePendingRequest(requestKey, true);
      // 生成取消 token
      config.cancelToken = new axios.CancelToken((cancelFn) => {
        pendingRequests.set(requestKey, cancelFn);
      });
    }

    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
http.interceptors.response.use(
  (response) => {
    // 如果没有使用 AbortController，则使用内部的取消机制
    if (!response.config.signal) {
      const requestKey = generateRequestKey(response.config);
      removePendingRequest(requestKey); // 请求完成，移除队列
    }

    const data = response.data;
    // 如果没有返回状态码，则默认成功
    if (!data.code) {
      return data;
    }
    if (data.code === 0) {
      return data.data;
    } else {
      // 统一错误提示
      if (typeof uni !== "undefined") {
        uni.showToast({
          icon: "none",
          duration: 3000,
          title: data.desc || "请求失败",
        });
      }
      // 登录过期处理
      if (data.code === 401 || data.code === 403) {
        removeToken();
        if (typeof uni !== "undefined") {
          uni.reLaunch({ url: "/pages/login/login" });
        }
      }
      return Promise.reject(data);
    }
  },
  (error) => {
    let message = "服务器错误，请稍后再试";

    // 处理取消请求的情况
    if (axios.isCancel(error) || error.code === "ERR_CANCELED") {
      // 对于取消的请求，我们不显示错误提示，直接返回拒绝的Promise
      return Promise.reject({
        code: "ERR_CANCELED",
        message: "请求已取消",
        isCancel: true,
      });
    }
    // 处理超时
    else if (error.code === "ECONNABORTED") {
      message = "请求超时，请检查网络";
    }
    // 处理网络错误
    else if (error.message && error.message.includes("Network")) {
      message = "网络连接失败，请检查网络";
    }

    // 只有非取消的请求才显示错误提示
    if (
      typeof uni !== "undefined" &&
      !axios.isCancel(error) &&
      error.code !== "ERR_CANCELED"
    ) {
      uni.showToast({
        icon: "none",
        duration: 3000,
        title: message,
      });
    }

    return Promise.reject(error);
  }
);

/**
 * 上传文件
 */
const upload = (
  url,
  {
    filePath,
    name = "file",
    formData = {},
    header = {},
    signal,
    ...options
  } = {}
) => {
  const requestKey = `upload_${url}_${filePath}`;

  return new Promise((resolve, reject) => {
    const uploadTask = uni.uploadFile({
      url: `${env.baseUrl}${url}`,
      filePath,
      name,
      formData,
      header: {
        ...header,
        ...(getToken() ? { Authorization: "Bearer " + getToken() } : {}),
      },
      success: (res) => {
        pendingRequests.delete(requestKey);
        try {
          if (typeof res.data === "string") {
            res.data = JSONBig({ storeAsString: true }).parse(res.data);
          }
        } catch (e) {}
        resolve(res);
      },
      fail: (err) => {
        pendingRequests.delete(requestKey);
        reject(err);
      },
      ...options,
    });

    // 支持 AbortController
    if (signal) {
      const onAbort = () => {
        uploadTask.abort();
        const error = new Error("Upload aborted");
        error.code = "ERR_CANCELED";
        error.isCancel = true;
        reject(error);
        signal.removeEventListener("abort", onAbort);
      };

      if (signal.aborted) {
        onAbort();
      } else {
        signal.addEventListener("abort", onAbort);
      }
    } else {
      // 使用内部的取消机制
      pendingRequests.set(requestKey, () => uploadTask.abort());
    }
  });
};

/**
 * 下载文件
 */
const download = (url, { header = {}, signal, ...options } = {}) => {
  const requestKey = `download_${url}`;

  return new Promise((resolve, reject) => {
    const downloadTask = uni.downloadFile({
      url: `${env.baseUrl}${url}`,
      header: {
        ...header,
        ...(getToken() ? { Authorization: "Bearer " + getToken() } : {}),
      },
      success: (res) => {
        pendingRequests.delete(requestKey);
        resolve(res);
      },
      fail: (err) => {
        pendingRequests.delete(requestKey);
        reject(err);
      },
      ...options,
    });

    // 支持 AbortController
    if (signal) {
      const onAbort = () => {
        downloadTask.abort();
        const error = new Error("Download aborted");
        error.code = "ERR_CANCELED";
        error.isCancel = true;
        reject(error);
        signal.removeEventListener("abort", onAbort);
      };

      if (signal.aborted) {
        onAbort();
      } else {
        signal.addEventListener("abort", onAbort);
      }
    } else {
      // 使用内部的取消机制
      pendingRequests.set(requestKey, () => downloadTask.abort());
    }
  });
};

export default http;
export { upload, download, removePendingRequest };
